home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 20
/
Cream of the Crop 20 (Terry Blount) (1996).iso
/
program
/
javnl005.zip
/
javnl005.txt
< prev
Wrap
Text File
|
1996-05-14
|
16KB
|
510 lines
Issue #005
May, 1996
Contents:
Comparing C/C++ with Java Part 5 - Multiple Inheritance
Sorting in Java
Java Program Packaging Part 3 - Protected/Default
Performance - Method Call Overhead
COMPARING C/C++ WITH JAVA PART 5 - MULTIPLE INHERITANCE
Suppose that you have two C++ classes:
class A {
public:
int x;
void f();
};
class B {
public:
int y;
void g();
};
and a third class that derives or inherits ("extends") from both of
these:
class C : public A, public B {
// stuff
};
Inheriting from multiple base classes is called "multiple inheritance"
or MI for short.
Like templates that we discussed in issue #004, multiple inheritance
adds to the complexity of C++, while offering a solution to some
particular kinds of programming problems. One type of issue with
programming using MI is in deciding which of a set of conflicting
inherited names "wins".
Java does not have multiple inheritance. It does, however, have a way
of doing some of what MI is intended for, relative to inheriting
attributes. In Java there is a language feature called an interface,
which looks like this:
public interface Orderable {
// return < 0 if p1 < p2, 0 if equal, > 0 if p1 > p2
public int compareTo(Object p1, Object p2);
}
This looks somewhat like a class, except that all the methods are
abstract, that is, are not implemented immediately but serve as
placeholders.
What is an interface used for? Suppose that you want to ensure that a
particular class has certain properties, in the present case that it
defines the method compareTo() to order objects. You can enforce this
by requiring that the class implement interface Orderable:
public class xxx implements Orderable {
public int compareTo(Object p1, Object p2)
{
int n1 = ((Integer)p1).intValue();
int n2 = ((Integer)p2).intValue();
return n1 - n2;
}
}
Why do we care about this? In the next section we will talk about
sorting in Java. To write a semi-general sort method, it's necessary
to assume that the objects within a Vector of objects to be sorted
have some ordering method available to rank them. Java by default has
no way of ordering two arbitrary objects.
By defining an Orderable interface, and either sorting a vector of
Orderables (that is, a vector of object types where the type is
defined to implement Orderable), or sorting a Vector of Objects with a
compareTo() method passed to the sort routine via a method wrapper
(see next section), we can ensure that a compareTo() method is
available.
An interface is sort of like a base class for a class. If you have
an Orderable reference:
Orderable or = null;
it's possible to assign to it a reference to an object type that
implements Orderable:
xxx x = new xxx();
or = x;
Again, if we have an Orderable object reference, we can be sure that a
method call like:
or.compareTo(p1, p2)
will be valid.
SORTING IN JAVA
In the last issue we talked about sorting in Java and said that
there's no approach to sorting that's really similar to qsort() in
C/C++. A couple of people wrote to me about this and suggested a
technique that does in fact have some similarities.
The idea is to write a sort method that accepts a Vector of Object
references, along with a class object instance that is a wrapper for a
compareTo() method as illustrated above. The sort routine will
iterate over the vector and call out to the compare method to
determine the ordering of any two objects. Specifically, this would
look like:
import java.util.Vector;
// Orderable interface
interface Orderable {
// return < 0 if p1 < p2, 0 if equal, > 0 if p1 > p2
public int compareTo(Object p1, Object p2);
};
// wrapper for a compareTo() method for ordering Strings
class Ord implements Orderable {
public int compareTo(Object p1, Object p2)
{
return ((String)p1).compareTo(((String)p2));
}
}
public class Sort {
public static void sort(Vector v, Orderable or)
{
if (v == null || or == null)
; // give error of some kind
// get vector size
int n = v.size();
// sort
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
// do comparison
if (or.compareTo(v.elementAt(i),
v.elementAt(j)) > 0) {
Object ti = v.elementAt(i);
Object tj = v.elementAt(j);
v.setElementAt(tj, i);
v.setElementAt(ti, j);
}
}
}
}
// driver program
public static void main(String args[])
{
Vector v = new Vector();
int N = 100;
int i = 0;
// add some strings
for (i = 0; i < N; i++)
v.addElement("xxx" + i);
// sort them
Sort.sort(v, new Ord());
// display the sorted list
for (i = 0; i < N; i++)
System.out.println((String)v.elementAt(i));
}
}
This code can be tuned in various ways (starting with the sort
algorithm) but is illustrative of the technique. We can implement any
sort strategy we want on a Vector of objects simply by changing the
ordering method. For example, saying:
class Ordrev implements Orderable {
public int compareTo(Object p1, Object p2)
{
return -((String)p1).compareTo(((String)p2));
}
}
...
Sort.sort(v, new Ordrev());
will reverse the sorting order for Strings. In this particular
example, Strings have a compareTo() method already defined, and we
simply cast the Object references to Strings and call this method.
Note that if the wrong compareTo() wrapper instance is used, then an
illegal cast will be attempted, resulting in an exception being
thrown. For example, the above case expects a String, and will
generate an exception ("ClassCastException") if the objects we pass in
are actually Integers. The "instanceof" operator can be used to help
sort things out.
In production code we'd have Orderable defined in a separate source
file. Ord might or might not be in its own file, depending on
stylistic preferences. Ord is simply a wrapper for a particular
compareTo() method. In C or C++ we would pass in a function pointer
directly, but Java has no user-visible pointers and no global
functions.
If we critique this approach and compare it to qsort(), there are some
notable differences and some similarities:
1. This approach is higher-level than qsort(), because it
doesn't fool with pointers and sizes of objects and so on.
2. This approach cannot be used to directly sort vectors of
fundamental data types like int or double. They must be
sorted using object wrappers.
3. Both approaches require calling out to a function or
method that is used to order el